package configimpl

import (
	"context"
	"errors"
	"fmt"
	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/services/admin/config"
	"go-caipu/pkg/services/admin/config/models"
	"go-caipu/pkg/services/dto"
	"go-caipu/pkg/util"
	"gorm.io/gorm"
)

type store interface {
	GetSysConfigPage(ctx context.Context, cmd config.GetSysConfigPageCommand) (data []config.SysConfig, num int64, err error)
	Get(ctx context.Context, cmd config.GetSysConfigCommand) (config.SysConfig, error)
	Insert(ctx context.Context, post config.SysConfig) error
	Update(ctx context.Context, post config.SysConfig) error
	Remove(ctx context.Context, cmd config.RemoveSysConfigCommand) error
	GetConfigsByKey(ctx context.Context, cmd config.GetConfigsByKeyCommand) (data []config.SysConfig, err error)
}
type sqlStore struct {
	db     *gorm.DB
	logger log.Logger
}

func ProvideStore(db *gorm.DB) sqlStore {
	return sqlStore{
		db:     db,
		logger: log.New("dept.store"),
	}
}

func (s sqlStore) GetSysConfigPage(ctx context.Context, cmd config.GetSysConfigPageCommand) (result []config.SysConfig, num int64, err error) {
	var items []models.SysConfig
	err = s.db.Model(&models.SysConfig{}).Scopes(
		dto.MakeCondition(cmd.GetNeedSearch()),
		dto.Paginate(cmd.GetPageSize(), cmd.GetPageIndex()),
	).Find(&items).Limit(-1).Offset(-1).Count(&num).Error
	if err != nil {
		return
	}
	for _, v := range items {
		result = append(result, ConvertToDTO(v))
	}
	return
}
func ConvertToDTO(model models.SysConfig) config.SysConfig {
	result := config.SysConfig{
		ConfigId:    model.ConfigId,
		ConfigName:  model.ConfigName,
		ConfigKey:   model.ConfigKey,
		ConfigValue: model.ConfigValue,
		Sort:        model.Sort,
		ConfigType:  model.ConfigType,
		IsFrontend:  model.IsFrontend,
		Remark:      model.Remark,
		ControlBy:   model.ControlBy,
		ModelTime:   model.ModelTime,
	}
	return result
}
func (s sqlStore) Get(ctx context.Context, cmd config.GetSysConfigCommand) (result config.SysConfig, err error) {
	var data models.SysConfig
	err = s.db.Model(&data).First(&data, cmd.Id).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New(fmt.Sprintf("ConfigId=%d record Not found", cmd.Id))
		return
	}
	if err != nil {
		s.logger.Log(fmt.Sprintf("get  config=%d  error:%s", cmd.Id, err.Error()))
		return
	}
	return ConvertToDTO(data), nil
}
func ConvertToDT(model config.SysConfig, cmd *models.SysConfig) {
	cmd.ConfigId = model.ConfigId
	cmd.ConfigName = model.ConfigName
	cmd.ConfigKey = model.ConfigKey
	value, err := util.ConvertConfigValue(model.ConfigValue)
	if err != nil {
		cmd.ConfigValue = "0"
	} else {
		cmd.ConfigValue = value
	}
	cmd.Sort = model.Sort
	cmd.ConfigType = model.ConfigType
	cmd.IsFrontend = model.IsFrontend
	cmd.Remark = model.Remark
	util.ConvertConfigValue(cmd.ConfigValue)
}

func (s sqlStore) Insert(ctx context.Context, cmd config.SysConfig) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysConfig
	ConvertToDT(cmd, &data)
	data.CreatedAt = cmd.CreatedAt
	data.CreateBy = cmd.CreateBy

	err = tx.Create(&data).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("insert  config  error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Update(ctx context.Context, cmd config.SysConfig) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	//查询当前配置名称是否存在
	var data models.SysConfig
	err = s.db.Model(&data).First(&data, cmd.ConfigId).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("check SysConfig id=%d is exists error:%s", cmd.ConfigId, err.Error()))
		return err
	}
	ConvertToDT(cmd, &data)
	data.UpdatedAt = cmd.UpdatedAt
	data.UpdateBy = cmd.UpdateBy
	err = tx.Save(&data).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("update  config  error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Remove(ctx context.Context, cmd config.RemoveSysConfigCommand) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysConfig
	err = tx.Model(&models.SysConfig{}).Delete(&data, cmd.Ids).Error
	if err != nil {
		return err
	}
	return
}
func (s sqlStore) GetConfigsByKey(ctx context.Context, cmd config.GetConfigsByKeyCommand) (data []config.SysConfig, err error) {
	var result []models.SysConfig
	err = s.db.Model(result).Scopes(dto.MakeCondition(cmd.GetNeedSearch())).Find(&result).Error
	if err != nil {
		return nil, err
	}
	for _, v := range result {
		data = append(data, ConvertToDTO(v))
	}
	return
}
